/******************************************************************************
 *      Mestrado em Ciência da Computação - UFMS
 *		Redes de Computadores - Prof. Dr. Ronaldo Alves Ferreira
 *		Alunos: Geraldo Landre, Marcel Tolentino, Vinícius Bueno
 *****************************************************************************/
/* tcprtt.c - tcprtt */

#include "my_socket.h"
#include "tcpfms.h"
#include "tcb.h"
#include "tcp.h"

int tmclear(int port, void *msg);

/*------------------------------------------------------------------------
 *  tcprtt - do round trip time estimates & cong. window processing
 *------------------------------------------------------------------------
 */
int tcprtt(struct tcb *ptcb)
{
    int	rrt,		/* raw round trip		*/
        delta;		/* deviation from smoothed	*/

    rrt = tmclear(thread_getport(output_thread), MKEVENT(RETRANSMIT, ptcb- (struct tcb *)&tcbtab[0]));
    if (rrt != SYSERR && ptcb->tcb_ostate != TCPO_REXMT) {
        if (ptcb->tcb_srt == 0)
                ptcb->tcb_srt = rrt<<3;	/* prime the pump */
        /*
         * "srt" is scaled X 8 here, so this is really:
         *	delta = rrt - srt
         */
        delta = rrt - (ptcb->tcb_srt>>3);
        ptcb->tcb_srt += delta;		/* srt = srt + delta/8	*/
        if (delta < 0)
                delta = -delta;
        /*
         * "rtde" is scaled X 4 here, so this is really:
         *	rtde = rtde + (|delta| - rtde)/4
         */
        ptcb->tcb_rtde += delta - (ptcb->tcb_rtde>>2);
        /*
         * "srt" is scaled X 8, rtde scaled X 4, so this is:
         *	rto = srt + 2 * rtde
         */
        ptcb->tcb_rexmt = ((ptcb->tcb_srt>>2)+ptcb->tcb_rtde)>>1;
        if (ptcb->tcb_rexmt < TCP_MINRXT)
                ptcb->tcb_rexmt = TCP_MINRXT;
    }
    if (ptcb->tcb_cwnd < ptcb->tcb_ssthresh)
        ptcb->tcb_cwnd += ptcb->tcb_smss;
    else
        ptcb->tcb_cwnd += (ptcb->tcb_smss * ptcb->tcb_smss) /
                ptcb->tcb_cwnd;
    return OK;
}
